package com.whsxt.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whsxt.domain.Prod;
import com.whsxt.domain.ProdComm;
import com.whsxt.domain.ProdTagReference;
import com.whsxt.domain.Sku;
import com.whsxt.mapper.ProdCommMapper;
import com.whsxt.mapper.ProdMapper;
import com.whsxt.mapper.ProdTagReferenceMapper;
import com.whsxt.service.ProdService;
import com.whsxt.service.ProdTagReferenceService;
import com.whsxt.service.SkuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: caoqingwen
 * @CreateTime: 2021-03-15 14:19
 * @Description: ${Description}
 */
@Service
@Slf4j
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod> implements ProdService {


    @Autowired
    private ProdMapper prodMapper;

    @Autowired
    private SkuService skuService;

    @Autowired
    private ProdTagReferenceService prodTagReferenceService;

    @Autowired
    private ProdTagReferenceMapper prodTagReferenceMapper;

    @Autowired
    private ProdCommMapper prodCommMapper;


    /**
     * 分页查询商品
     *
     * @param page
     * @param prod
     * @return
     */
    @Override
    public IPage<Prod> findProdPage(Page<Prod> page, Prod prod) {
        page.addOrder(OrderItem.desc("create_time"));
        return prodMapper.selectPage(page, new LambdaQueryWrapper<Prod>()
                .eq(prod.getStatus() != null, Prod::getStatus, prod.getStatus())
                .like(StringUtils.isNotBlank(prod.getProdName()), Prod::getProdName, prod.getProdName())
        );
    }


    /**
     * 新增商品,需要三张表
     * <p>
     * Prod
     * Sku
     * prod_tag_reference
     *
     * @param prod
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Prod prod) {
        log.info("新增商品：{}", JSON.toJSONString(prod));
        prod.setCreateTime(new Date());
        prod.setUpdateTime(new Date());
        prod.setSoldNum(0);
        prod.setShopId(1L);
        prod.setVersion(0);
        if ("1".equals(String.valueOf(prod.getStatus()))) {
            //上架时间
            prod.setPutawayTime(new Date());
        }
        //配送方式
        prod.setDeliveryMode(JSON.toJSONString(prod.getDeliveryModeVo()));
        //插入
        int insert = prodMapper.insert(prod);
        if (insert > 0) {
            //操作sku
            handlerSku(prod.getSkuList(), prod.getProdId());
            //操作prod_tag_reference
            handlerTagReference(prod.getTagList(), prod.getProdId());
        }
        return insert > 0;
    }


    /**
     * 处理商品和标签的中间表
     *
     * @param tagList
     * @param prodId
     */
    private void handlerTagReference(List<Long> tagList, Long prodId) {
        if (!CollectionUtils.isEmpty(tagList)) {
            List<ProdTagReference> prodTagReferences = new ArrayList<>();
            tagList.forEach(tagId -> {
                ProdTagReference prodTagReference = new ProdTagReference();
                prodTagReference.setCreateTime(new Date());
                prodTagReference.setProdId(prodId);
                prodTagReference.setShopId(1L);
                prodTagReference.setTagId(tagId);
                prodTagReference.setStatus(1);
                prodTagReferences.add(prodTagReference);
            });
            prodTagReferenceService.saveBatch(prodTagReferences);
        }
    }


    /**
     * 处理商品和sku的关系
     *
     * @param skuList
     * @param prodId
     */
    private void handlerSku(List<Sku> skuList, Long prodId) {
        skuList.forEach(sku -> {
            sku.setUpdateTime(new Date());
            sku.setRecTime(new Date());
            sku.setProdId(prodId);
            sku.setVersion(0);
            sku.setIsDelete(0);
        });
        skuService.saveBatch(skuList);
    }


    /**
     * 根据区间查询商品的总条数
     *
     * @param t1
     * @param t2
     * @return
     */
    @Override
    public Integer getTotalCount(Date t1, Date t2) {
        Integer count = prodMapper.selectCount(new LambdaQueryWrapper<Prod>()
                .between(t1 != null && t2 != null, Prod::getUpdateTime, t1, t2)
        );
        return count;
    }


    /**
     * 分页查询需要导入的商品集合
     *
     * @param page
     * @param t1
     * @param t2
     * @return
     */
    @Override
    public Page<Prod> findProdByPageToEs(Page<Prod> page, Date t1, Date t2) {
        Page<Prod> prodPage = prodMapper.selectPage(page, new LambdaQueryWrapper<Prod>()
                .between(t1 != null && t2 != null, Prod::getUpdateTime, t1, t2)
        );
        List<Prod> prodList = prodPage.getRecords();
        if (!CollectionUtils.isEmpty(prodList)) {
            //拿到商品的ids
            List<Long> ids = prodList.stream().map(Prod::getProdId).collect(Collectors.toList());
            //查询标签
            List<ProdTagReference> prodTagReferenceList = prodTagReferenceMapper.selectList(new LambdaQueryWrapper<ProdTagReference>()
                    .in(ProdTagReference::getProdId, ids)
            );

            prodList.forEach(prod -> {
                List<ProdTagReference> referenceList = prodTagReferenceList.stream()
                        .filter(prodTagReference -> prodTagReference.getProdId().equals(prod.getProdId()))
                        .collect(Collectors.toList());
                prod.setTagList(referenceList.stream().map(ProdTagReference::getTagId).collect(Collectors.toList()));
            });

            //处理好评和好评率
            List<ProdComm> prodCommList = prodCommMapper.selectList(new LambdaQueryWrapper<ProdComm>()
                    .in(ProdComm::getProdId, ids)
            );
            //得到好评数量和总评数
            prodList.forEach(prod -> {
                //拿到这个商品的评论
                List<ProdComm> totalComm = prodCommList.stream().filter(prodComm -> prodComm.getProdId().equals(prod.getProdId())).collect(Collectors.toList());

                boolean flag = true;
                if (!CollectionUtils.isEmpty(totalComm)) {
                    //有总评数量
                    List<ProdComm> goodComm = totalComm.stream().filter(prodComm -> prodComm.getEvaluate().equals(0)).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(goodComm)) {

                        flag = false;

                        int goodSize = goodComm.size();
                        int totalSize = totalComm.size();
                        //设置好评数
                        prod.setPraiseNumber((long) goodSize);
                        //设置好评率
                        BigDecimal goodSizeBig = new BigDecimal(goodSize);
                        BigDecimal totalSizeBig = new BigDecimal(totalSize);
                        //计算好评率
                        BigDecimal good = goodSizeBig.divide(totalSizeBig, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
                        prod.setPositiveRating(good);
                    }
                }

                if (flag) {
                    //设置好评数
                    prod.setPraiseNumber(0L);
                    prod.setPositiveRating(new BigDecimal("0"));
                }
            });
        }
        return prodPage;
    }


    /**
     * 前台根据id查询商品信息（包括了sku）
     *
     * @param prodId
     * @return
     */
    @Override
    public Prod findProdAndSkuById(Long prodId) {
        Prod prod = prodMapper.selectById(prodId);
        if (prod == null) {
            return null;
        }

        //查询sku的集合
        List<Sku> skuList = skuService.list(new LambdaQueryWrapper<Sku>()
                .eq(Sku::getProdId, prodId)
        );

        prod.setSkuList(skuList);
        return prod;
    }


    /**
     * 扣减mysql库存
     *
     * @param stockMap
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStock(Map<String, Map<Long, Integer>> stockMap) {
        Map<Long, Integer> prodStock = stockMap.get("prod");

        Set<Long> prodIds = prodStock.keySet();
        List<Prod> prodList = prodMapper.selectBatchIds(prodIds);
        prodList.forEach(prod -> {
            Integer stock = prodStock.get(prod.getProdId());
            int finalStock = prod.getTotalStocks() + stock;
            if (finalStock <= 0) {
                throw new RuntimeException("库存不足");
            }
            prod.setTotalStocks(finalStock);
            prod.setUpdateTime(new Date());
        });
        //统一修改
        this.updateBatchById(prodList);

        Map<Long, Integer> skuStock = stockMap.get("sku");
        Set<Long> skuIds = skuStock.keySet();
        List<Sku> skuList = skuService.listByIds(skuIds);
        skuList.forEach(sku -> {
            Integer stock = skuStock.get(sku.getSkuId());
            int finalStock = sku.getActualStocks() + stock;
            if (finalStock <= 0) {
                throw new RuntimeException("库存不足");
            }
            sku.setActualStocks(finalStock);
            sku.setStocks(finalStock);
            sku.setUpdateTime(new Date());
        });
        skuService.updateBatchById(skuList);
    }
}
